home *** CD-ROM | disk | FTP | other *** search
/ 9-Digit Zip Code Directory / 9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO / z4src.zip / BSSTR.C < prev    next >
C/C++ Source or Header  |  1995-06-08  |  20KB  |  667 lines

  1. //----------------------------------------------------------------------------
  2. //                            MODULE DESCRIPTION
  3. //
  4. //  Module:    bsstr.c
  5. //   Title:    Base library
  6. //  Notice:    John M. Weeder
  7. //                 Copyright (c) 1993. All rights reserved.
  8. //             This module contains proprietary information and should be 
  9. //                treated as confidential.
  10. //
  11. //----------------------------------------------------------------------------
  12. //                           MAINTENANCE HISTORY
  13. //
  14. // $Workfile$
  15. // $Revision$
  16. //   $Author$
  17. //     $Date$
  18. //      $Log$    
  19. //
  20. //----------------------------------------------------------------------------
  21. //                             MODULE NARRATIVE
  22. //
  23. //
  24. //    This module contains utility string functions.
  25. //
  26. //    The code in this module should be written entirely in C. 
  27. //    Do not use any C++ constructs.
  28. //
  29. //    This module is portable to:
  30. //        DOS 3.X+
  31. //        MS Windows 3.X+
  32. //        OS/2 2.X+
  33. //        OS/2 2.0 PM
  34. //        SCO UNIX.
  35. //
  36. //    The following compilers are supported:
  37. //        MSC 6.0A
  38. //        MSC/C++ 7.0
  39. //        Borland C++ 3.1 for DOS
  40. //        Borland C++ 1.0 for OS/2 2.X
  41. //        SCO UNIX cc
  42. //
  43. //----------------------------------------------------------------------------
  44. #include <bs.h>
  45.  
  46. //----------------------------------------------------------------------------
  47. //    UNIX Portability.
  48. //    This is a hack but it kind of works...
  49. //----------------------------------------------------------------------------
  50. #if OS_UNIX
  51. #    define strtoul    strtol
  52. #endif
  53.  
  54.  
  55. //----------------------------------------------------------------------------
  56. //   Description:    Sort routine used by qsort to sort an array of pointers
  57. //                          to strings.
  58. //    Parameters:    see qsort()
  59. //       Returns:    see qsort()
  60. //----------------------------------------------------------------------------
  61. static int __strsort__(const void *pv1, const void *pv2)
  62. {
  63.     return strcmp(*((PPSZ)pv1), *((PPSZ)pv2));
  64. }
  65.  
  66.  
  67. //----------------------------------------------------------------------------
  68. //   Description:    Convert a length of consectutive null terminated strings,
  69. //                        ending with a double NULL into an array. An array of 
  70. //                        sufficient size will be allocated if needed. Array is 
  71. //                        NULL terminated.
  72. //    Parameters:    psz        Pointer to array of strings.
  73. //                        ppsz        Pointer to array of string pointers. If NULL, an
  74. //                                    array will be allocated.
  75. //                        cArray    Size of string pointer array.
  76. //       Returns:    Pointer to array.
  77. //----------------------------------------------------------------------------
  78. PPSZ FN_E str2array(PSZ psz, PPSZ ppsz, SIZET cArray)
  79. {
  80.     SIZET i, cCount;
  81.  
  82.     Assert(psz);
  83.     cCount = strarraysize(psz);
  84.     if (!ppsz)
  85.         {
  86.         if ((ppsz = (PPSZ)MemAlloc((cCount + 1) * sizeof(PSZ))) == NULL)
  87.             return NULL;
  88.  
  89.         }
  90.     if (!cArray)
  91.         cArray = cCount + 1;
  92.     for (i = 0; i < cArray - 1; ++i)
  93.         {
  94.         ppsz[i] = psz;
  95.         psz = strchr(psz, '\0') + 1;
  96.         }
  97.     ppsz[i] = NULL;                       // NULL terminate list
  98.     return ppsz;
  99. }
  100.  
  101.  
  102. //----------------------------------------------------------------------------
  103. //   Description:    Convert an array of pointers to string to a single array
  104. //                          of strings with a double NULL at the end. 
  105. //                        An array is allocated for the concatenated strings if 
  106. //                        needed.
  107. //    Parameters:    ppsz        Pointer to array of string pointers. The array
  108. //                                    must be null terminated.
  109. //                        cCount   Number of elements in array, 0 = search for null
  110. //                                    terminator.
  111. //                        psz        Buffer. 
  112. //                                    If null, a buffer of the correct size is allocated.
  113. //       Returns:    Pointer to array.
  114. //----------------------------------------------------------------------------
  115. PSZ FN_E strarray2str(PPSZ ppsz, SIZET cCount, PSZ pszBuf)
  116. {
  117.     SIZET i, cSize, cLen;
  118.     PSZ psz;
  119.  
  120.     Assert(ppsz);
  121.     if (!cCount)
  122.         cCount = strarraycnt(ppsz);
  123.     for (cSize = i = 0; i < cCount; ++i)
  124.         {
  125.         cLen = strlen(ppsz[i]);
  126.         if (MAX_SIZET - cSize - 1 < cLen)
  127.             return NULL;                        // Bigger than 64K 
  128.         cSize += cLen + 1;
  129.         if (cSize == MAX_SIZET)
  130.             return NULL;                        // No room for double null 
  131.         }
  132.  
  133.     if (pszBuf == NULL)
  134.         if ((pszBuf = (PSZ)MemAlloc(cSize)) == NULL)
  135.             return NULL;
  136.  
  137.     for (psz = pszBuf, i = 0; i < cCount; ++i)
  138.         {
  139.         strcpy(psz, ppsz[i]);
  140.         psz = strchr(psz, '\0') + 1;
  141.         }
  142.     psz[0] = '\0';                            // Add second null 
  143.     return pszBuf;
  144. }
  145.  
  146.  
  147. //----------------------------------------------------------------------------
  148. //   Description:    Counts the number of string pointers in a NULL
  149. //                          terminated array
  150. //    Parameters:    ppszStr        Pointer to an array of pointers.
  151. //       Returns:    Number of strings found (Array is null terminated)
  152. //----------------------------------------------------------------------------
  153. SIZET FN_E strarraycnt(PPSZ ppsz)
  154. {
  155.    SIZET i = 0;
  156.  
  157.     Assert(ppsz);
  158.    for (i = 0; ppsz[i]; ++i)
  159.       ;
  160.    
  161.    return i;
  162. }
  163.  
  164.  
  165. //----------------------------------------------------------------------------
  166. //   Description:    Sort an array of pointers to strings in ascending order.
  167. //    Parameters:    psz        String to match
  168. //                        ppsz        Pointer to array of string pointers. The array
  169. //                                    must be null terminated.
  170. //                        cCount   Number of elements in array, 0 = search for null
  171. //                                    terminator.
  172. //       Returns:    Pointer to matched element or NULL
  173. //----------------------------------------------------------------------------
  174. PCSZ FN_E strarrayfind(PSZ psz, PPSZ ppsz, SIZET cCount)
  175. {
  176.     Assert(psz && ppsz);
  177.    if (cCount == 0)
  178.         cCount = strarraycnt(ppsz);
  179.     if (cCount)
  180.         {
  181.         ppsz = (PPSZ)bsearch(&psz, ppsz, cCount, sizeof(PSZ), __strsort__);
  182.         psz = ppsz ? *ppsz: NULL;
  183.         }
  184.     else
  185.         psz = NULL;
  186.  
  187.     return psz;
  188. }
  189.  
  190.  
  191. //----------------------------------------------------------------------------
  192. //   Description:    Determine the number of strings in an array of ascii text
  193. //                          terminated with a double null.
  194. //    Parameters:    psz        Pointer to array of strings.
  195. //       Returns:    Number of null terminated strings in array.
  196. //----------------------------------------------------------------------------
  197. SIZET FN_E strarraysize(PCSZ pcsz)
  198. {
  199.     SIZET i = 0;
  200.  
  201.     Assert(pcsz);
  202.     for (;;)
  203.         {
  204.         pcsz = strchr(pcsz, '\0') + 1;
  205.  
  206.         i++;
  207.         if (pcsz[0] == '\0')
  208.             break;
  209.         }
  210.     return i;
  211. }
  212.  
  213.  
  214. //----------------------------------------------------------------------------
  215. //   Description:    Sort an array of pointers to strings in ascending order.
  216. //    Parameters:    ppsz        Pointer to array of string pointers. The array
  217. //                                    must be null terminated.
  218. //                        cCount   Number of elements in array, 0 = search for null
  219. //                                    terminator.
  220. //       Returns:    TRUE if successful.
  221. //----------------------------------------------------------------------------
  222. BOOL FN_E strarraysort(PPSZ ppsz, SIZET cCount)
  223. {
  224.     Assert(ppsz);
  225.    if (cCount == 0)
  226.         cCount = strarraycnt(ppsz);
  227.     if (cCount > 1)
  228.         qsort(ppsz, cCount, sizeof(PSZ), __strsort__);
  229.    return TRUE;
  230. }
  231.  
  232.  
  233. //----------------------------------------------------------------------------
  234. //   Description:    Concatenate a string. Placing single space between the 
  235. //                          strings. 
  236. //                        Does not add a space if the destination is empty or already
  237. //                        contains a space.
  238. //    Parameters:    pszDst        Pointer to destination string.
  239. //                        pcszSrc        Pointer to source string
  240. //       Returns:    Pointer to destination
  241. //----------------------------------------------------------------------------
  242. PSZ FN_E strcats(PSZ pszDst, PCSZ pcszSrc)
  243. {
  244.     PSZ psz;
  245.  
  246.     Assert(pszDst && pcszSrc);
  247.  
  248.                                                     // Skip wshitespace in source
  249.     while (pcszSrc[0] && isascii(pcszSrc[0]) && isspace(pcszSrc[0]))
  250.         pcszSrc++;
  251.     if (!pcszSrc[0])                            // String contained only whitespace
  252.         return pszDst;
  253.  
  254.     psz = strchr(pszDst, '\0');            // Append space if needed
  255.     if (pszDst[0] && (!isascii(*(psz - 1)) || !isspace(*(psz - 1))))
  256.         *psz++ = ' ';
  257.  
  258.     strcpy(psz, pcszSrc);
  259.     return (PSZ)pszDst;
  260. }
  261.  
  262.  
  263. //----------------------------------------------------------------------------
  264. //   Description:    Count the number of characters 'c' in a string
  265. //    Parameters:    psz        String
  266. //                        c            Character to count
  267. //       Returns:    Number of characters
  268. //----------------------------------------------------------------------------
  269. SIZET FN_E strcnt(PSZ psz, CHAR ch)
  270. {
  271.     SIZET cCount = 0;
  272.  
  273.     Assert(psz);
  274.     for (; psz[0]; ++psz)                    // Count characters 
  275.       if (psz[0] == ch)
  276.           cCount++;
  277.  
  278.    return cCount;
  279. }
  280.  
  281.  
  282. //----------------------------------------------------------------------------
  283. //   Description:    Delete a sub-string from a string.
  284. //    Parameters:    psz        String
  285. //                        cOffset     Offset to delete at
  286. //                        cCount    Number of characters to delete
  287. //       Returns:    Pointer to string.
  288. //----------------------------------------------------------------------------
  289. PSZ FN_E    strdel(PSZ psz, SIZET cOffset, SIZET cCount)
  290. {
  291.     Assert(psz);
  292.  
  293.     memdel((PVOID)psz, strlen(psz) + 1, cOffset, cCount);
  294.     return psz;
  295. }
  296.  
  297.  
  298. //----------------------------------------------------------------------------
  299. //   Description:    Extracts an element from a delimited list.
  300. //    Parameters:    psz            Buffer for results.
  301. //                        pcszList        List to search.
  302. //                        cWhich        Which component. 0..n-1
  303. //                        pcszSep        List of separators
  304. //       Returns:    TRUE if successful and element
  305. //----------------------------------------------------------------------------
  306. BOOL FN_E strextract(PSZ psz, PCSZ pcszList, SIZET cWhich, PCSZ pcszSep)
  307. {
  308.     Assert(psz && pcszList && pcszSep);
  309.  
  310.     while (pcszList[0])
  311.         {
  312.         SIZET cb = strcspn(pcszList, pcszSep);
  313.  
  314.         if (cWhich == 0)
  315.             {
  316.             memcpy(psz, pcszList, cb);
  317.             psz[cb] = '\0';
  318.             return TRUE;
  319.             }
  320.         cWhich--;
  321.         pcszList += cb;
  322.         if (pcszList[0])
  323.             pcszList++;
  324.         }
  325.     return FALSE;
  326. }
  327.  
  328.  
  329. //----------------------------------------------------------------------------
  330. //   Description:    Create a hash value for a sting into a ULONG.
  331. //    Parameters:    pszHash        Name to create a hash value for.
  332. //       Returns:    Hash value for name.
  333. //----------------------------------------------------------------------------
  334. ULONG FN_E strhash(PCSZ pszHash)
  335. {
  336.     Assert(pszHash);
  337.     return (ULONG)CrcCalc((PBYTE)pszHash, strlen(pszHash));
  338. }
  339.  
  340.  
  341. //----------------------------------------------------------------------------
  342. //   Description:    Insert a string into another string. Assumes there is 
  343. //                          sufficient space for the expanded buffer.
  344. //    Parameters:    psz        Destination string
  345. //                        pszIns    String to insert
  346. //                        cOffset     Offset to add add.
  347. //       Returns:    Pointer to buffer.
  348. //----------------------------------------------------------------------------
  349. PSZ FN_E strins(PSZ psz, PSZ pszIns, SIZET cOffset)
  350. {
  351.     SIZET    cLen, cIns;
  352.  
  353.     Assert(psz && pszIns);
  354.     cLen = strlen(psz) + 1;
  355.     cIns = strlen(pszIns);
  356.     memins(psz, cLen, pszIns, cIns, MIN(cOffset, cLen));
  357.     return psz;
  358. }
  359.  
  360.  
  361. //----------------------------------------------------------------------------
  362. //   Description:    Insert a string into another string. Assumes there is 
  363. //                          sufficient space for the expanded buffer.
  364. //    Parameters:    psz        Destination string
  365. //                        pszIns    String to insert
  366. //                        cOffset     Offset to add add.
  367. //       Returns:    Pointer to buffer.
  368. //----------------------------------------------------------------------------
  369. PSZ FN_E strinsc(PSZ psz, CHAR chIns, SIZET cOffset)
  370. {
  371.     SIZET    cLen;
  372.  
  373.     Assert(psz);
  374.     cLen = strlen(psz) + 1;
  375.     memins(psz, cLen, &chIns, 1, MIN(cOffset, cLen));
  376.     return psz;
  377. }
  378.  
  379.  
  380. //----------------------------------------------------------------------------
  381. //   Description:    Copy up to 'cch' chars from the source string to the destination
  382. //                        string.  This function always guarantees the destination string
  383. //                        is NULL terminated. 
  384. //    Parameters:    pszDest        Destination string
  385. //                        pszSrc        Source string.
  386. //                        cch            Size of destination buffer.
  387. //       Returns:    Pointer to destination string.
  388. //----------------------------------------------------------------------------
  389. PSZ FN_E strnzcpy(PSZ pszDest, PCSZ pszSrc, SIZET cch)
  390. {
  391.     Assert(pszDest && pszSrc);
  392.     if (cch == 1)
  393.         pszDest[0] = '\0';                     // A trivial buffer size
  394.     else if (cch > 1)
  395.         {
  396.         SIZET cbLen = strlen(pszSrc);       // Get length of source string
  397.         if (cbLen >= cch)
  398.             {
  399.             memcpy(pszDest, pszSrc, cch - 1);
  400.             pszDest[cch - 1] = '\0';
  401.             }
  402.         else
  403.             strcpy(pszDest, pszSrc);      // String fits
  404.         }
  405.     return pszDest;                     // return destination
  406. }
  407.  
  408. //----------------------------------------------------------------------------
  409. //   Description: Return the ordinal suffix for a number.
  410. //    Parameters:    lVal        Number
  411. //       Returns:    Pointer to ordinal suffix (capitalized)
  412. //----------------------------------------------------------------------------
  413. PSZ FN_E strord(LONG lVal)
  414. {
  415.     if ((lVal % 100) > 10 && (lVal %100) <14)
  416.         return "TH";
  417.     if ((lVal % 10) == 1)
  418.         return "ST";
  419.     if ((lVal % 10) == 2)
  420.         return "ND";
  421.     if ((lVal % 10) == 3)
  422.         return "RD";
  423.     return "TH";
  424. }
  425.  
  426. //----------------------------------------------------------------------------
  427. //   Description: Skip to next whittespace character in string.
  428. //    Parameters:    psz        String
  429. //       Returns:    Pointer to first non-whitespace character in string 
  430. //                        or NULL.
  431. //----------------------------------------------------------------------------
  432. PSZ FN_E strskip2ws(PSZ psz)
  433. {
  434.     if (psz == NULL)
  435.         return NULL;
  436.    while (psz[0] != '\0' && isascii(psz[0]) && !isspace(psz[0]))
  437.       psz++;
  438.  
  439.    return psz[0] ? psz: NULL;
  440. }
  441.  
  442.  
  443. //----------------------------------------------------------------------------
  444. //   Description:    Skip over whitespace in a string
  445. //    Parameters:    psz        Pointer to string.
  446. //       Returns:    TRUE if successful.
  447. //----------------------------------------------------------------------------
  448. PSZ FN_E strskipws(PCSZ psz)
  449. {
  450.     if (psz == NULL)
  451.         return NULL;
  452.    while (psz[0] && isascii(psz[0]) && isspace(psz[0]))
  453.       psz++;
  454.  
  455.     return (PSZ)psz;
  456. }
  457.  
  458.  
  459. //----------------------------------------------------------------------------
  460. //   Description:    Skip over whitespace in a string
  461. //    Parameters:    psz        Pointer to string.
  462. //       Returns:    TRUE if successful.
  463. //----------------------------------------------------------------------------
  464. PSZ FN_E strskipzero(PCSZ psz)
  465. {
  466.     if (psz == NULL)
  467.         return NULL;
  468.     if (psz[0] == '0')
  469.         {
  470.        while (psz[0] == '0')
  471.           psz++;
  472.         if (!isascii(psz[0]) || !isdigit(psz[0]))
  473.             psz--;
  474.         }
  475.     return (PSZ)psz;
  476. }
  477.  
  478.  
  479. //----------------------------------------------------------------------------
  480. //   Description:    Strip all control characters from a string
  481. //    Parameters:    psz        String.
  482. //       Returns:    Pointer to string
  483. //----------------------------------------------------------------------------
  484. PSZ FN_E strstripcntrl(PSZ psz)
  485. {
  486.    PSZ pszDst = psz;
  487.  
  488.  
  489.     Assert(psz);
  490.    do
  491.       {
  492.       if (!iscntrl(psz[0]))
  493.             *pszDst++ = *psz++;
  494.       else
  495.             psz++;
  496.       }
  497.    while (psz[0]);
  498.    pszDst[0] = '\0';
  499.    return psz;
  500. }
  501.  
  502.  
  503. //----------------------------------------------------------------------------
  504. //   Description:    Trim space from both ends of string
  505. //    Parameters:    psz        String.
  506. //       Returns:    Pointer to string
  507. //----------------------------------------------------------------------------
  508. PSZ FN_E strtrim(PSZ psz)
  509. {
  510.     return strtrimleft(strtrimright(psz));
  511. }
  512.  
  513.  
  514. //----------------------------------------------------------------------------
  515. //   Description:    Trim space from left of string
  516. //    Parameters:    psz        String.
  517. //       Returns:    Pointer to string
  518. //----------------------------------------------------------------------------
  519. PSZ FN_E strtrimleft(PSZ psz)
  520. {
  521.     PSZ pszWS = psz;
  522.     Assert(psz);
  523.     while (isascii(*pszWS) && isspace(*pszWS))
  524.         pszWS++;
  525.     if (pszWS != psz)
  526.         strcpy(psz, pszWS);
  527.     return psz;
  528. }
  529.  
  530.  
  531. //----------------------------------------------------------------------------
  532. //   Description:    Trim space from right of string
  533. //    Parameters:    psz        String.
  534. //       Returns:    Pointer to string
  535. //----------------------------------------------------------------------------
  536. PSZ FN_E strtrimright(PSZ psz)
  537. {
  538.     Assert(psz);
  539.     if (*psz)
  540.         {
  541.         PSZ pszWS = strchr(psz, '\0') - 1;
  542.         for (;;)
  543.             {
  544.            if (!isascii(*pszWS) || !isspace(*pszWS))
  545.                {
  546.                pszWS[1] = '\0';
  547.                return psz;
  548.                }
  549.             if (pszWS == psz)
  550.                 break;
  551.            pszWS--;
  552.             }
  553.         psz[0] = '\0';
  554.         }
  555.     return psz;
  556. }
  557.  
  558.  
  559. //----------------------------------------------------------------------------
  560. //   Description:    Run standard test suite
  561. //    Parameters:    sTest        Test to run.
  562. //                                        0        Run all default tests (except).
  563. //       Returns:    TRUE if successful.
  564. //----------------------------------------------------------------------------
  565. #if COMPILE_TEST
  566. BOOL FN StringTest(SHORT sTest)
  567. {
  568. static PSZ apsz[] =
  569.     {
  570.     "-2147483647",
  571.     "2147483647",
  572.     "-2147483648",
  573.     "2147483648",
  574.     "-32767",
  575.     "32767",
  576.     "-32768",
  577.     "32768",
  578.     "65536",
  579.     "065536",
  580.     " 65536 ",
  581.     "65537",
  582.     "0xFFFF",
  583.     "0xFFFF",
  584.     "0x10000",
  585.     "0xFFFFFFFF",
  586.     "4294967295",
  587.     NULL
  588.     };
  589. static PSZ apszArray[20];
  590. static CHAR szStr[100] = "d\0f\0g\0c\0b\0e\0i\0h\0a\0";
  591.  
  592.     CHAR szBuf[10];
  593.     PSZ psz;
  594.     SIZET i;
  595.     SHORT s;
  596.     USHORT us;
  597.     LONG l;
  598.     ULONG ul;
  599.  
  600.     NOTUSED(sTest);
  601.     Output("Count = %d (5)\n", strcnt("dabcddefk9d", 'd'));
  602.     Output("Hash = %08lX\n", strhash("ABCDEF"));
  603.     Output("String = [%s]\n", strnzcpy(szBuf, "ABCDEFGHIJK", 5));
  604.     Output("String = [%s]\n", strskipws("   This is a test   "));
  605.     Output("String = [%s]\n", strtrimleft("   This is a test   "));
  606.     Output("String = [%s]\n", strtrimright("   This is a test   "));
  607.     Output("String = [%s]\n", strskipws("   This is a test   "));
  608.  
  609.     for (i = 0; strextract(szBuf, ";test+is-a/test", i, ";+-/"); ++i)
  610.         Output("Extract %2d: [%s]\n", i, szBuf);
  611.  
  612.     for (i = 0; apsz[i]; ++i)
  613.         {
  614.         Output("String = %s\n", apsz[i]);
  615.         if (strvalidshort(apsz[i], &s))
  616.             Output("SHORT  = %hd\n", s);
  617.         else
  618.             Output("SHORT  = invalid!\n");
  619.  
  620.         if (strvalidushort(apsz[i], &us))
  621.             Output("USHORT = %hu\n", us);
  622.         else
  623.             Output("USHORT = invalid!\n");
  624.  
  625.         if (strvalidlong(apsz[i], &l))
  626.             Output("LONG   = %ld\n", l);
  627.         else 
  628.             Output("LONG   = invalid!\n");
  629.  
  630.         if (strvalidulong(apsz[i], &ul))
  631.             Output("ULONG  = %lu\n", ul);
  632.         else
  633.             Output("ULONG  = invalid!\n");
  634.         }
  635.  
  636.     str2array(szStr, apszArray, 0);
  637.     for (i = 0; apszArray[i]; ++i)
  638.         Output("  %s\n", apszArray[i]);
  639.     Output("\n");
  640.     strarraysort(apszArray, 0);
  641.     for (i = 0; apszArray[i]; ++i)
  642.         Output("  %s\n", apszArray[i]);
  643.  
  644.     if ((psz = (PSZ)strarrayfind("a", apszArray, 0)) == NULL
  645.     || strcmp(psz, "a") != 0
  646.      || strarrayfind("z", apszArray, 0) != NULL)
  647.         return FALSE;
  648.  
  649.     if(!strisphone("09ayAY"))
  650.         return FALSE;
  651.     if(strisphone("09ayAYqQzZ"))
  652.         return FALSE;
  653.     if(!strisnumeric("0123456789"))
  654.         return FALSE;
  655.     if(strisnumeric("0123456789a"))
  656.         return FALSE;
  657. //    if(strisnumeric2("0123456789ABCZ"))
  658. //        return FALSE;
  659.     if (!strisvalid("a(abqa", "??[a-z~q]+?[A-Z]*\\a"))
  660.         return FALSE;
  661.     return TRUE;
  662. }
  663. #endif
  664. //----------------------------------------------------------------------------
  665. //------------------------------- End of File --------------------------------
  666. //----------------------------------------------------------------------------
  667.